/*
 * 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[遇见知启蒙，邂逅框架梦]
 * 
 * https://zhiqim.org/project/zhiqim_framework/zhiqim_kernel.htm
 *
 * Zhiqim Kernel is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package org.zhiqim.kernel;

import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.net.BindException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

import org.zhiqim.kernel.constants.SignConstants;
import org.zhiqim.kernel.constants.ZhiqimConstants;
import org.zhiqim.kernel.control.Threadx;
import org.zhiqim.kernel.logging.Log;
import org.zhiqim.kernel.logging.LogFactory;
import org.zhiqim.kernel.util.Closes;
import org.zhiqim.kernel.util.Strings;
import org.zhiqim.kernel.util.Systems;

/**
 * 知启蒙工程监听类 ，由ZhiqimCommand发起的命令在这里执行
 * 
 * 1. -s表示启动
 * 2. -c表示工程退出
 * 3. -i表示查看信息
 * 4. -t表示测试配置文件（TODO 暂未实现）
 * 5. -r表示重新加载配置（TODO 暂未实现）
 * 6. -h表示帮助
 * 7. -?表示帮助
 * 
 * @version v1.0.0 @author zouzhigang 2014-2-27 新建与整理
 */
final class ZhiqimMonitor extends Threadx implements ZhiqimConstants, SignConstants
{
    private static final Log logger = LogFactory.getLog(ZhiqimMonitor.class);
    
    private ServerSocket serverSocket;
    private int port;
    
    //只允许包创建实例
    ZhiqimMonitor(int port)
    {
        this.port = port;
    }
    
    /** 线程名 */
    protected String getThreadName()
    {
        return "ZhiqimMonitor";
    }
    
    /**********************************************************************************/
    //开启&关闭&循环运行
    /**********************************************************************************/
    
    /** 开启 */
    protected boolean openBefore()
    {
        try
        {
            serverSocket = new ServerSocket(port, 5, InetAddress.getByName(_127_0_0_1_));
            serverSocket.setReuseAddress(true);
            return true;
        }
        catch (BindException e)
        {
            logger.error("启动监视线程失败，工程已启动或端口[boot.port]被占用");
            return false;
        }
        catch (Exception e)
        {
            logger.error("启动监视线程失败", e);
            return false;
        }
    }
    
    /** 关闭 */
    protected void closeAfter()
    {
        Closes.closeIgnoreException(serverSocket);
    }
    
    /** 运行 */
    public void loop()
    {
        Socket socket = null;String cmd = null;
        try
        {
            socket = serverSocket.accept();
            
            LineNumberReader line = new LineNumberReader(new InputStreamReader(socket.getInputStream()));
            String lineKey = line.readLine();
            if (!Z_NAME.equals(lineKey))
                return;
            
            cmd = line.readLine();
            if (Z_INFO_C.equals(cmd))
            {//查看信息
                StringBuilder strb = new StringBuilder()
                    .append("响应结果:").append(_BR_)
                    .append("PID:").append(Systems.getPid()).append(_BR_);
                
                socket.getOutputStream().write(Strings.getBytesUTF8(strb.toString()));
                socket.getOutputStream().flush();
            }
            else if (Z_TEST_C.equals(cmd) || Z_RELOAD_C.equals(cmd))
            {//测试配置文件和重新加载配置文件 TODO 暂未实现
                StringBuilder strb = new StringBuilder()
                    .append("响应结果:").append(_BR_)
                    .append("暂未实现").append(_BR_);
                
                socket.getOutputStream().write(Strings.getBytesUTF8(strb.toString()));
                socket.getOutputStream().flush();
            }
            else if (Z_LORDER_C.equals(cmd))
            {//热部署
                String serviceId = line.readLine();
                boolean b = false;
                if (Zhiqim.closeService(serviceId))
                {
                    b = Zhiqim.openService(serviceId);
                }
                String ret = b ? serviceId+"热部署完成" : serviceId+"热部署失败";
                StringBuilder strb = new StringBuilder()
                    .append("响应结果:").append(_BR_)
                    .append(ret).append(_BR_);
                
                socket.getOutputStream().write(Strings.getBytesUTF8(strb.toString()));
                socket.getOutputStream().flush();
            }
            else if (Z_HELP_C.equals(cmd) || Z_QUESTION_C.equals(cmd))
            {//帮助
                StringBuilder strb = new StringBuilder()
                    .append("响应结果:").append(_BR_)
                    .append("-s    启动工程").append(_BR_)
                    .append("-c    关闭工程").append(_BR_)
                    .append("-i    查看信息").append(_BR_)
                    .append("-t    测试配置文件").append(_BR_)
                    .append("-r    重新加载配置").append(_BR_)
                    .append("-l    热部署服务").append(_BR_)
                    .append("-h    帮助").append(_BR_)
                    .append("-?    帮助").append(_BR_);
                
                socket.getOutputStream().write(Strings.getBytesUTF8(strb.toString()));
                socket.getOutputStream().flush();
            }
        }
        catch(Exception e)
        {
            logger.error(e);
        }
        finally
        {
            Closes.closeIgnoreException(socket);
            if (Z_CLOSE_C.equals(cmd))
            {//接受到退出工程命令
                closeNotInterrupt();
                System.exit(0);
            }
        }
    }
}
